package com.speedtickets.rest.controller;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.codehaus.jettison.json.JSONException;

import com.speedtickets.rest.beans.TicketBean;
import com.speedtickets.rest.exceptions.ForbiddenKeyException;
import com.speedtickets.rest.exceptions.InvalidKeyException;
import com.speedtickets.rest.exceptions.ValidationException;
import com.speedtickets.rest.models.Ticket;
import com.speedtickets.rest.services.ITicketService;
import com.speedtickets.rest.services.factory.TicketServiceFactory;
import com.speedtickets.rest.utils.AuthorizationUtils;
import com.speedtickets.rest.utils.HandleEvents;
import com.speedtickets.rest.utils.ParseUtils;
import com.speedtickets.rest.validators.Validator;

@Path("/tickets")
public class TicketController {

	private static ITicketService _ticketService = TicketServiceFactory.getInstance().getTicketServices();
	
	private Validator _validator = new Validator();
	
	private AuthorizationUtils _authorize = new AuthorizationUtils();
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public Response postTicket( TicketBean ticketBean, @QueryParam("apiKey") String apiKey ) throws JSONException, IllegalArgumentException, IllegalAccessException{
		
		try {
			_authorize.retrictKeys(apiKey);
			_validator.validate(ticketBean);
			
			Ticket ticket = ParseUtils.parse(ticketBean);
			_ticketService.createTicket(ticket);
			
			return Response.status(201).entity(HandleEvents.handleSucess(ticket.getId(), "tickets", "POST", 201)).build();
		} catch (InvalidKeyException ike){
			return Response.status(401).entity(HandleEvents.handleUnauthorized(401)).build();
		} catch (ForbiddenKeyException fke){
			return Response.status(403).entity(HandleEvents.handleForbidden(403)).build();
		} catch (ValidationException ve){
			return Response.status(400).entity(HandleEvents.handleBadRequest(ve.getMessage(), 400)).build();
		} catch(Exception e){
			return Response.status(500).entity(HandleEvents.handleServerError(500)).build();
		} 
		
	}
	
	@PUT
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response putTicket(@PathParam("id") String id, TicketBean ticketBean, @QueryParam("apiKey") String apiKey) throws JSONException, IllegalArgumentException, IllegalAccessException, ValidationException{
		
		try {
			_authorize.retrictKeys(apiKey);
			Ticket ticketDB = _ticketService.findTicketById(Long.parseLong(id));
			if(ticketDB == null){
				return Response.status(404).entity(HandleEvents.handleNotFoundError(id)).build();
			}
			Ticket ticketUpdate = ParseUtils.parse(ticketBean);
			if(ticketDB != null){
				ticketUpdate.setId(ticketDB.getId());
			}
			_validator.validate(ticketBean);
			_ticketService.updateTicket(ticketUpdate);
			return Response.status(200).entity(HandleEvents.handleSucess(ticketUpdate.getId(), "tickets", "PUT", 200)).build();
		} catch (InvalidKeyException ike){
			return Response.status(401).entity(HandleEvents.handleUnauthorized(401)).build();
		} catch (ForbiddenKeyException fke){
			return Response.status(403).entity(HandleEvents.handleForbidden(403)).build();
		} catch (ValidationException ve){
			return Response.status(400).entity(HandleEvents.handleBadRequest(ve.getMessage(), 400)).build();
		} catch(Exception e){
			return Response.status(500).entity(HandleEvents.handleServerError(500)).build();
		}
	}

	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getTickets(@QueryParam("apiKey") String apiKey, @QueryParam("limit") Integer limit, @QueryParam("offset") Integer offset ) throws JSONException{
		
		try {
			_authorize.noRestriction(apiKey);
			List<Ticket>ticketsList = new ArrayList<Ticket>();
			//Verifica se os parametros limit e offset estão sendo 
			//passados na query, se estiverem utiliza mecanismo de 
			//paginação, senão retorna os resultados por completo
			if(limit != null && offset != null){
				ticketsList = _ticketService.findAllTickets(limit, offset);
			} else {
				ticketsList = _ticketService.findAllTickets();
			}
			List<TicketBean> beanList = new ArrayList<TicketBean>();
			for (Ticket ticket : ticketsList) {
				TicketBean bean = ParseUtils.parse(ticket);
				beanList.add(bean);
			}
			return Response.status(200).entity(beanList).build();
		}
		catch (InvalidKeyException ike){
			return Response.status(401).entity(HandleEvents.handleUnauthorized(401)).build();
		} catch(Exception e){
			return Response.status(500).entity(HandleEvents.handleServerError(500)).build();
		}
		
	}
	
	@GET
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getTicket(@PathParam("id") String id, @QueryParam("apiKey") String apiKey) throws JSONException{
		try{
			_authorize.noRestriction(apiKey);
			Ticket ticket = _ticketService.findTicketById(Long.parseLong(id));
			if(ticket == null){
				return Response.status(404).entity(HandleEvents.handleNotFoundError(id)).build();
			}
			TicketBean bean = ParseUtils.parse(ticket);
			return Response.status(200).entity(bean).build();
		} catch (InvalidKeyException ike){
			return Response.status(401).entity(HandleEvents.handleUnauthorized(401)).build();
		} catch(Exception e){
			return Response.status(500).entity(HandleEvents.handleServerError(500)).build();
		}
	}
	
	@DELETE
	@Path("/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response deleteTickets(@PathParam("id") String id, @QueryParam("apiKey") String apiKey) throws JSONException{
		try {	
			_authorize.retrictKeys(apiKey);
			Ticket ticketDB = _ticketService.findTicketById(Long.parseLong(id));
			if(ticketDB == null){
				return Response.status(404).entity(HandleEvents.handleNotFoundError(id)).build();
			}
			_ticketService.deleteTicket(ticketDB);
			return Response.status(200).entity(HandleEvents.handleSucess(ticketDB.getId(), "tickets", "DELETE", 200)).build();
		} catch (InvalidKeyException ike){
			return Response.status(401).entity(HandleEvents.handleUnauthorized(401)).build();
		} catch (ForbiddenKeyException fke){
			return Response.status(403).entity(HandleEvents.handleForbidden(403)).build();
		} catch(Exception e){
			return Response.status(500).entity(HandleEvents.handleServerError(500)).build();
		}
	}
		
}
